今天來介紹隱含的強制轉型。
隱含強制轉型,就是 JS 在一些運算上,自動幫你做轉型。
如果再不明白背後運作的原理,的確會用到滿肚子怒火。
探討隱含轉型之前,先了解 +
做了什麼事。
ES5 section 11.6.1 的規格
var a = "42";
var b = "0";
a + b; // "420"
var c = 42;
var d = 0;
c + d; // 42
如果 +
兩側有任一個是 string,會串接兩側的 string。
如果 +
兩側都是 number,會計算兩側的值總和。
var e = [1,2];
var f = [3,4];
e + f; // "1,23,4"
如果有一個 Object (含 array),會先呼叫 toPrimitive 來處理,後續就和 ToNumber 相同。所以 array 進行 valueOf() 拿不到基本型別就失敗,後續就用 toString() 方法變為 "1,2" 和 "3,4"。接著就是字串的串接了。
var a = {
valueOf: function() { return 42; },
toString: function() { return 4; }
}
a + ""; // "42"
String( a ); // "4"
a + ""
涉及了在 a 這個值上調用 valueOf() 的動作,回傳值會透過內部的 toString() 抽象運算被轉為一個 string。而 String(a) 只會直接調用 toString()。
+
經過 toPrimive 運作方式,會先找 valueOf() 的動作,如果沒有的話,會再找 toString()。這樣就會回傳 42。
String() 會直接呼叫 toString 的方法,所以會回傳 4。
四則運算其他成員呢?
會將 String 轉成 Number,因為這些運算子只有運算的功能。
var a= "3.14"
a - 0; // 3.14
a * 1; // 3.14
a / 1; // 3.14
假設了解了物件在隱含強制轉型的原理,還是會有奇怪的範例。(之後會解釋)
[] + {}; // "[object Object]"
{} + []; // 0
+"1" | +2 | +[3] | +{} | |
---|---|---|---|---|
"1" | "11" | "12" | "13" | "1[object Object]" |
2 | "21" | 4 | "23" | "2[object object]" |
[3] | "31" | "32" | "33" | "3[object object]" |
{} | 1 | 2 | 3 | "[object Object][object Object]" |
+
toNumber 明確的強制轉型。+
以外的四則運算?var a = "3.14"
a - 0; // 3.14
a * 1; // 3.14
a / 1; // 3.14
+
以外的四則運算子只被定義用於數值減法運算。也適用在 array 運算。
var a = [3];
var b = [1];
a - b; // 2
array 會先由 toString() 強制轉型為 string,再強制轉型為 number。
var a = true;
a + 2; // 3
下面的功能,在於判斷 array 裡面的真值數量。
function onlyOne(){
var sum = 0;
for (var i=0; i < arguments.length; i++){
if (arguments[i]){ // 若第 i 項為真值,就執行。
sum += arguments[i]; // 隱性轉型的重點。
}
}
return sum == 1; // 若總數為 1,回傳 true。
}
哪些部分會隱含的轉換成 boolean
前四個是判斷式,需要判斷 Boolean 才能執行內部程式。
都是先從左邊的運算元判斷。
| a||b
| a = truthy | a = falsy |
| - | :-: | :-: |
| b = truthy | a | b |
| b = falsy | a | b |
a&&b |
a = truthy | a = falsy |
---|---|---|
b = truthy | b | a |
b = falsy | b | a |
測試範例,一起來了解 JS 在背後做了哪些隱含強制轉型吧!
var a = 42;
var b = null;
var c = "foo";
if ( a && ( b || c )) {
console.log("yep");
}
裡面做了幾件事。
b || c
,因為 b 是 false,回傳 c 的值 "foo"。a && "foo"
,因為 a 是 true,回傳 c 的值 "foo"。Symbol 轉 String
var s1 = Symbol( "cool" );
String(s1); // "Symbol(cool)"
s1 + ""; // TypeError
還沒,明天是第七章的最後部分。
會講相等性,寬鬆相等與嚴格相等。
主要是寬鬆的部分,裡面有用到隱含強制轉型。
最後有關係式的比較。
明天見!